﻿//-----------------------------------------------------------------------
// <copyright file="MultipointInkCanvas.cs" author="viettp@live.com">
//     Copyright (c) PHUOCVIET. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System.Diagnostics.CodeAnalysis;
using Microsoft.Multipoint.Sdk.Interop;

namespace MultipointControls
{
    using System;
    using System.Collections;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using Microsoft.Multipoint.Sdk;
    using Microsoft.Multipoint.Sdk.Controls;

    enum MultipointInkCanvasEditingMode
    {
        Ink,
        SingleSelect,
        MultiSelect,
        EraseByPoint,
        EraseByStroke
    };

    public class MultipointInkCanvas : InkCanvas, IMultipointMouseEvents, IMultipointGenericDeviceEvents, IDisposable
    {
        #region Private Fields
        Hashtable dicStroke;
        #endregion

        #region Public Properties

        public Hashtable MouseDrawingAttributes
        {
            get { return (Hashtable)GetValue(MouseDrawingAttributesProperty); }
            set { SetValue(MouseDrawingAttributesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MouseDrawingAttributes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MouseDrawingAttributesProperty =
            DependencyProperty.Register("MouseDrawingAttributes", typeof(Hashtable), typeof(MultipointInkCanvas), new FrameworkPropertyMetadata(new Hashtable()));

        #endregion

        #region MultipointEvents

        public static readonly RoutedEvent MultipointClickEvent = EventManager.RegisterRoutedEvent("MultipointClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MultipointInkCanvas));

        #endregion


        #region Constructor

        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "WPF Eventing model makes it very difficult to function w/o static ctor")]
        static MultipointInkCanvas()
        {
            // Set ClipToBounds property to true
            Type owner = typeof(MultipointInkCanvas);
            ClipToBoundsProperty.OverrideMetadata(owner, new FrameworkPropertyMetadata(true));

            RegisterClassHandler(MultipointMouseEvents.MultipointMouseDownEvent, OnMultipointMouseDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseUpEvent, OnMultipointMouseUpThunk, false);

            RegisterClassHandler(MultipointMouseEvents.MultipointMouseLeftButtonDownEvent, OnMultipointMouseLeftButtonDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseLeftButtonUpEvent, OnMultipointMouseLeftButtonUpThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseRightButtonDownEvent, OnMultipointMouseRightButtonDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseRightButtonUpEvent, OnMultipointMouseRightButtonUpThunk, false);

            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseDownEvent, OnMultipointPreviewMouseDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseUpEvent, OnMultipointPreviewMouseUpThunk, false);

            RegisterClassHandler(MultipointMouseEvents.MultipointMouseEnterEvent, OnMultipointMouseEnterThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseLeaveEvent, OnMultipointMouseLeaveThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseMoveEvent, OnMultipointMouseMoveThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointMouseWheelEvent, OnMultipointMouseWheelThunk, false);

            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseLeftButtonDownEvent, OnMultipointPreviewMouseLeftButtonDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseLeftButtonUpEvent, OnMultipointPreviewMouseLeftButtonUpThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseRightButtonDownEvent, OnMultipointPreviewMouseRightButtonDownThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseRightButtonUpEvent, OnMultipointPreviewMouseRightButtonUpThunk, false);

            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseMoveEvent, OnMultipointPreviewMouseMoveThunk, false);
            RegisterClassHandler(MultipointMouseEvents.MultipointPreviewMouseWheelEvent, OnMultipointPreviewMouseWheelThunk, false);

            // Generic Events
            RegisterClassHandler(MultipointGenericDeviceEvents.MultipointDeviceDownEvent, OnMultipointDeviceDownThunk, false);
            RegisterClassHandler(MultipointGenericDeviceEvents.MultipointDeviceUpEvent, OnMultipointDeviceUpThunk, false);
            RegisterClassHandler(MultipointGenericDeviceEvents.MultipointDeviceMoveEvent, OnMultipointDeviceMoveThunk, false);

            // Own Events
            
        }

        public MultipointInkCanvas()
        {
            DrawingAttributes da = new DrawingAttributes();
            da.Color = Colors.Purple;
            da.Height = 3; da.Width = 3;

            dicStroke = new Hashtable();
        }

        #endregion

        #region EventThunks

        private static void OnMultipointMouseDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointMouseDown(sender, e);

                var args = (MultipointMouseEventArgs)e;
                switch (args.Buttons)
                {
                    case RawMouseButtons.LeftDown:
                        args.RoutedEvent = MultipointMouseEvents.MultipointMouseLeftButtonDownEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                    case RawMouseButtons.RightDown:
                        args.RoutedEvent = MultipointMouseEvents.MultipointMouseRightButtonDownEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                }
            }
        }

        private static void OnMultipointMouseUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointMouseUp(sender, e);

                var args = (MultipointMouseEventArgs)e;
                switch (args.Buttons)
                {
                    case RawMouseButtons.LeftUp:
                        args.RoutedEvent = MultipointMouseEvents.MultipointMouseLeftButtonUpEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                    case RawMouseButtons.RightUp:
                        args.RoutedEvent = MultipointMouseEvents.MultipointMouseRightButtonUpEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                }
            }
        }

        private static void OnMultipointMouseLeftButtonDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointMouseLeftButtonDown(sender, e);
            }
        }

        private static void OnMultipointMouseLeftButtonUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointMouseLeftButtonUp(sender, e);
            }
        }

        private static void OnMultipointMouseRightButtonDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointMouseRightButtonDown(sender, e);
            }
        }

        private static void OnMultipointMouseRightButtonUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointMouseRightButtonUp(sender, e);
        }

        private static void OnMultipointPreviewMouseDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointPreviewMouseDown(sender, e);

                var args = e as MultipointMouseEventArgs;
                if (args == null) return;
                switch (args.Buttons)
                {
                    case RawMouseButtons.LeftDown:
                        args.RoutedEvent = MultipointMouseEvents.MultipointPreviewMouseLeftButtonDownEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                    case RawMouseButtons.RightDown:
                        args.RoutedEvent = MultipointMouseEvents.MultipointPreviewMouseRightButtonDownEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                }
            }
        }

        private static void OnMultipointPreviewMouseUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
            {
                eventThunk.OnMultipointPreviewMouseUp(sender, e);

                var args = e as MultipointMouseEventArgs;
                if (args == null) return;
                switch (args.Buttons)
                {
                    case RawMouseButtons.LeftUp:
                        args.RoutedEvent = MultipointMouseEvents.MultipointPreviewMouseLeftButtonUpEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                    case RawMouseButtons.RightUp:
                        args.RoutedEvent = MultipointMouseEvents.MultipointPreviewMouseRightButtonUpEvent;
                        args.Source = sender;
                        ((UIElement)args.Source).RaiseEvent(args);
                        break;
                }
            }
        }

        private static void OnMultipointMouseEnterThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointMouseEnter(sender, e);
        }

        private static void OnMultipointMouseLeaveThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointMouseLeave(sender, e);
        }

        private static void OnMultipointMouseMoveThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointMouseMove(sender, e);
        }

        private static void OnMultipointMouseWheelThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointMouseWheel(sender, e);
        }

        private static void OnMultipointPreviewMouseLeftButtonDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseLeftButtonDown(sender, e);
        }

        private static void OnMultipointPreviewMouseLeftButtonUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseLeftButtonUp(sender, e);
        }

        private static void OnMultipointPreviewMouseRightButtonDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseRightButtonDown(sender, e);
        }

        private static void OnMultipointPreviewMouseRightButtonUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseRightButtonUp(sender, e);
        }

        private static void OnMultipointPreviewMouseMoveThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseMove(sender, e);
        }

        private static void OnMultipointPreviewMouseWheelThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointPreviewMouseWheel(sender, e);
        }

        private static void OnMultipointDeviceDownThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointDeviceDown(sender, e);
        }

        private static void OnMultipointDeviceUpThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointDeviceUp(sender, e);
        }

        private static void OnMultipointDeviceMoveThunk(object sender, RoutedEventArgs e)
        {
            var eventThunk = sender as MultipointInkCanvas;
            if (eventThunk != null)
                eventThunk.OnMultipointDeviceMove(sender, e);
        }

        #endregion

        #region Protected Methods
        internal virtual void OnMultipointMouseDown(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointMouseUp(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointMouseLeftButtonDown(object sender, RoutedEventArgs e)
        {
            var args = e as MultipointMouseEventArgs;
            if (args == null) return;

            Point pt = this.PointFromScreen(args.DeviceInfo.DeviceVisual.Position);

            string mouseId = args.DeviceInfo.DeviceId;

            switch (this.EditingMode)
            {
                case InkCanvasEditingMode.EraseByPoint:
                    break;
                case InkCanvasEditingMode.EraseByStroke:
                    break;
                case InkCanvasEditingMode.GestureOnly:
                    break;
                case InkCanvasEditingMode.Ink:
                    {
                        if (!dicStroke.ContainsKey(mouseId))
                            dicStroke.Add(mouseId, null);
                        StylusPointCollection spc = new StylusPointCollection();
                        spc.Add(new StylusPoint(pt.X, pt.Y));
                        dicStroke[mouseId] = new Stroke(spc, MouseDrawingAttributes.ContainsKey(mouseId) ? (DrawingAttributes)MouseDrawingAttributes[mouseId] : DefaultDrawingAttributes);

                        this.Strokes.Add((Stroke)dicStroke[mouseId]);
                    }
                    break;
                case InkCanvasEditingMode.InkAndGesture:
                    break;
                case InkCanvasEditingMode.None:
                    break;
                case InkCanvasEditingMode.Select:
                    break;
            }

        }

        internal virtual void OnMultipointMouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            var args = e as MultipointMouseEventArgs;
            if (args == null) return;

            string mouseId = args.DeviceInfo.DeviceId;

            switch (this.EditingMode)
            {
                case InkCanvasEditingMode.EraseByPoint:
                    break;
                case InkCanvasEditingMode.EraseByStroke:
                    break;
                case InkCanvasEditingMode.GestureOnly:
                    break;
                case InkCanvasEditingMode.Ink:
                    {
                        if (!dicStroke.ContainsKey(mouseId))
                            dicStroke.Add(args.DeviceInfo.DeviceId, null);

                        if (dicStroke[mouseId] == null) return;

                        Point pt = this.PointFromScreen(args.DeviceInfo.DeviceVisual.Position);

                        ((Stroke)dicStroke[mouseId]).StylusPoints.Add(new StylusPoint(pt.X, pt.Y));
                    }
                    break;
                case InkCanvasEditingMode.InkAndGesture:
                    break;
                case InkCanvasEditingMode.None:
                    break;
                case InkCanvasEditingMode.Select:
                    break;
            }


            this.OnMultipointClick(args);
        }

        internal virtual void OnMultipointClick(MultipointMouseEventArgs args)
        {
        }

        internal virtual void OnMultipointMouseRightButtonDown(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointMouseRightButtonUp(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseDown(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointPreviewMouseUp(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointMouseEnter(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointMouseLeave(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointMouseMove(object sender, RoutedEventArgs e)
        {
            var args = e as MultipointMouseEventArgs;
            if (args == null) return;

            if (args.DeviceInfo.DeviceVisual.LeftButton == MultipointMouseButtonState.Released)
                return;

            string mouseId = args.DeviceInfo.DeviceId;

            switch (this.EditingMode)
            {
                case InkCanvasEditingMode.EraseByPoint:
                    break;
                case InkCanvasEditingMode.EraseByStroke:
                    break;
                case InkCanvasEditingMode.GestureOnly:
                    break;
                case InkCanvasEditingMode.Ink:
                    {
                        if (!dicStroke.ContainsKey(mouseId))
                        {
                            dicStroke.Add(mouseId, null);
                            return;
                        }
                        if (dicStroke[mouseId] == null) return;

                        Point pt = this.PointFromScreen(args.DeviceInfo.DeviceVisual.Position);

                        ((Stroke)dicStroke[mouseId]).StylusPoints.Add(new StylusPoint(pt.X, pt.Y));
                    }
                    break;
                case InkCanvasEditingMode.InkAndGesture:
                    break;
                case InkCanvasEditingMode.None:
                    break;
                case InkCanvasEditingMode.Select:
                    break;
            }
        }

        internal virtual void OnMultipointMouseWheel(object sender, RoutedEventArgs e)
        {
        }

        internal virtual void OnMultipointPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseLeftButtonUp(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseRightButtonDown(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseRightButtonUp(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseMove(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointPreviewMouseWheel(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointDeviceDown(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointDeviceUp(object sender, RoutedEventArgs e)
        { }

        internal virtual void OnMultipointDeviceMove(object sender, RoutedEventArgs e)
        { }
        #endregion

        #region Multipoint Mouse EventHandlers

        public event RoutedEventHandler MultipointClick
        {
            add
            {
                this.AddHandler(MultipointInkCanvas.MultipointClickEvent, value);
            }
            remove
            {
                this.RemoveHandler(MultipointInkCanvas.MultipointClickEvent, value);
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Dispose the class
        /// </summary>
        /// <param name="releaseUnmanaged">Release unmanaged resources as well</param>
        protected virtual void Dispose(bool releaseUnmanaged)
        {
            if (releaseUnmanaged)
            {
                // None to release
            }
        }

        #endregion


        #region IMultipointMouseEvents Members

        public event RoutedEventHandler MultipointMouseDownEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseDownHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseDownHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointMouseEnterEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseEnterHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseEnterHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointMouseLeaveEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseLeaveHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseLeaveHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointMouseMoveEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseMoveHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseMoveHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointMouseUpEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseUpHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseUpHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointMouseWheelEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointMouseWheelHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointMouseWheelHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointPreviewMouseDownEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointPreviewMouseDownHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointPreviewMouseDownHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointPreviewMouseMoveEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointPreviewMouseMoveHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointPreviewMouseMoveHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointPreviewMouseUpEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointPreviewMouseUpHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointPreviewMouseUpHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointPreviewMouseWheelEvent
        {
            add
            {
                MultipointMouseEvents.AddMultipointPreviewMouseWheelHandler(this, value);
            }

            remove
            {
                MultipointMouseEvents.RemoveMultipointPreviewMouseWheelHandler(this, value);
            }
        }

        public delegate void MultipointEditingModeChangedHandler(object sender, RoutedEventArgs e);
        public event MultipointEditingModeChangedHandler MultipointEditingModeChanged;
        

        #endregion

        #region IMultipointGenericDeviceEvents Members

        public event RoutedEventHandler MultipointDeviceDown
        {
            add
            {
                MultipointGenericDeviceEvents.AddDeviceDownHandler(this, value);
            }

            remove
            {
                MultipointGenericDeviceEvents.RemoveDeviceDownHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointDeviceMove
        {
            add
            {
                MultipointGenericDeviceEvents.AddDeviceMoveHandler(this, value);
            }

            remove
            {
                MultipointGenericDeviceEvents.RemoveDeviceMoveHandler(this, value);
            }
        }

        public event RoutedEventHandler MultipointDeviceUp
        {
            add
            {
                MultipointGenericDeviceEvents.AddDeviceUpHandler(this, value);
            }

            remove
            {
                MultipointGenericDeviceEvents.RemoveDeviceUpHandler(this, value);
            }
        }
        #endregion

        #region Private Methods

        private static void RegisterClassHandler(RoutedEvent routedEvent, RoutedEventHandler handler, bool handledEventsToo)
        {
            EventManager.RegisterClassHandler(typeof(UIElement), routedEvent, handler, handledEventsToo);
            EventManager.RegisterClassHandler(typeof(ContentElement), routedEvent, handler, handledEventsToo);
        }

        #endregion
    }
}
